import math

from strange_io import SIGNATURE, get_format, _load_bytearray
import strange_io.dynamic_integer as dynamic_integer

class StrangeArray:
    def __init__(self, array:list[bytes]=[]):
        self.array:list[bytes] = array

    def dump(self) -> list[bytes]:
        return self.array

    def load(self, array:list[bytes]):
        self.array = array

    def dump_bytes(self) -> bytes:
        return self.encode(self.array)

    def load_bytes(self, data: bytes):
        self.array = self.decode(data)

    def dump_file(self, path):
        out_file = bytearray()
        header = bytearray(SIGNATURE + b'array\n')
        out_file += header
        out_file += self.encode(self.array)
        with open(path, 'wb') as f:
            f.write(out_file)

    def load_file(self, path, ignore_type=False):
        if get_format(path) == b'array' or ignore_type:
            file = _load_bytearray(path, remove_type=True)
            self.array = self.decode(file)
        else:
            raise TypeError('Attempted to load non-array document as array document')

    @staticmethod
    def encode(array:list[bytes]) -> bytes:
        number = len(array)
        out = bytes()
        out += dynamic_integer.encode(number)[0]
        for i in array:
            number = len(i)
            out += dynamic_integer.encode(number)[0]
            out += i
        return out

    @staticmethod
    def decode(data:bytes) -> list[bytes]:
        data = bytearray(data)
        array_length = dynamic_integer.decode(data)[0]
        out = [b'' for _ in range(array_length)]
        for i in range(array_length):
            string_length = dynamic_integer.decode(data)[0]
            for j in range(string_length):
                out[i] += bytes([data[j]])
            for _ in range(string_length):
                del data[0]
        return out

#region list-like
    def append(self, array:bytes):
        self.array.append(array)

    def extend(self, array:list[bytes]):
        self.array.extend(array)

    def pop(self, index=None):
        return self.array.pop(index)

    def __getitem__(self, index):
        return self.array[index]

    def __setitem__(self, index, array):
        self.array[index] = array

    def __len__(self):
        return len(self.array)

    def __str__(self):
        return str(self.array)
#endregion
